package com.ob.web.core.config.exception;

import com.ob.core.constants.enums.SysResponseCode;
import com.ob.core.dto.R;
import com.ob.core.exception.ObException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.naming.ServiceUnavailableException;
import java.util.List;

/**
 * 全局异常处理器
 * @author jasmine
 */
@SuppressWarnings("ALL")
@RestControllerAdvice
public class ObGlobalExceptionHandler {
    private final Logger log = LoggerFactory.getLogger(ObGlobalExceptionHandler.class);

    private static String from;

    /**
     * 错误请求
     */
    @ExceptionHandler({IllegalArgumentException.class,ArticleException.class})
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public R illegalArgumentException(Exception exception) {
        log.error("GlobalExceptionHandler - illegalArgumentException [400] [{}] ", exception.getMessage());
        exception.printStackTrace();
        return R.fault(
                SysResponseCode.BAD_REQUEST.code(),
                exception.getMessage(),
                from);
    }

    /**
     * validation Exception
     */
    @ExceptionHandler({MethodArgumentNotValidException.class, BindException.class})//
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public R methodArgumentNotValidException(Exception exception) {
        String msg = "参数错误";
        if (exception instanceof BindException) {
            ObjectError objectError = ((BindException) exception).getAllErrors().get(0);
            msg = objectError.getDefaultMessage();
        } else if (exception instanceof MethodArgumentNotValidException) {
            List<FieldError> fieldErrors = ((MethodArgumentNotValidException)exception).getBindingResult().getFieldErrors();
            msg = fieldErrors.get(0).getDefaultMessage();
        }

        if (msg.startsWith("Failed to convert property value of type")) {
            msg = "参数错误";
        }

        log.error("GlobalExceptionHandler - {} [400] [{}] [{}]",
                exception.getClass().getSimpleName(),
                SysResponseCode.byCode(SysResponseCode.BAD_REQUEST.code()).msg(), msg);

        return R.fault(SysResponseCode.BAD_REQUEST.code(), msg, from);
    }

    /**
     * 异常 503
     */
    @ExceptionHandler({ServiceUnavailableException.class})
    @ResponseStatus(HttpStatus.SERVICE_UNAVAILABLE)
    public R exception503(Exception exception) {
        log.error("GlobalExceptionHandler - exception [503] [{}] [{}]", exception, exception.getMessage());
        exception.printStackTrace();
        return R.fault(
                SysResponseCode.SERVER_UNAVAILABLE.code(),
                exception.getMessage(),
                from);
    }

    /**
     * 全局异常 500
     */
    @ExceptionHandler({Exception.class, ObException.class, RuntimeException.class})
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public R exception(Exception exception) {
        log.error("GlobalExceptionHandler - exception [500] [{}] [{}]", exception, exception.getMessage());
        exception.printStackTrace();
        return R.fault(
                SysResponseCode.INTERNAL_SERVER_ERROR.code(),
                exception.getMessage(),
                from);
    }

    /**
     * 去掉static可配置响应体中的from字段
     * @param name
     */
    @Value("${spring.application.name}")
    public static void setFrom(String name) {
        from = "[" + (name == null ? "全局异常配置" : name) + "] - GlobalExceptionHandler";
    }
}
